#include <iostream>

#include <jsoncpp/json/json.h>

#include <string>

#include <vector>

#include "util.hpp"

#include "config.hpp"

#include "data.hpp"

#include "hot.hpp"

#include "service.hpp"

#include <thread>

void FileUtilTest(const std::string &filename){
    

   /*                    Test1                        */ 
   // Cloud::FileUtil fu(filename); // 实例化对象
   // std::cout<<fu.FileName()<<std::endl;
   // std::cout<<fu.FileSize()<<std::endl;
   // std::cout<<fu.LastATime()<<std::endl;
   // std::cout<<fu.LastMTime()<<std::endl;
    

   /*                    Test2                        */ 
    //Cloud::FileUtil fu(filename); // 实例化对象
    //std::string body; // 新的容器用于存放读取文件的数据
    //fu.GetContent(&body); // 读取文件数据至body
    //                      
    //Cloud::FileUtil nfu("./newfile.txt") ;
    //nfu.SetContent(body);
    // 此处可以使用 md5sum <filename> 来 查询对应的mf5匙来对比两者文件内容是否一致
  
    /*                    Test3                        */ 
    //Cloud::FileUtil fu(filename); // 实例化对象
    //fu.Compress("./newtestfile.lzip"); // 压缩文件

    /*  ---------------   Test4   -------------------  */ 
    // Cloud::FileUtil fu(filename); // 实例化对象
    // fu.CreateDirectory(); // 根据目录名创建目录与文件
    // std::vector<std::string> dirs;
    // fu.ScanDirectory(&dirs);
    // for(auto &str: dirs){
    //     std::cout<<str.c_str()<<std::endl;
    // }


    /*  ---------------   Test5   -------------------  */ 
    Cloud::FileUtil fu(filename); // 实例化对象
    Json::Value root; // 创建一个 Value 类型
                      
    root["Filename"] = fu.FileName().c_str(); // 以此对 Value 类型进行赋值
    root["FSize"] = fu.FileSize();
    root["LastATime"] = fu.LastATime();
    root["LastMTime"] = fu.LastMTime();
    
    std::string encoded;
    Cloud::JsonUtil::Serialize(root,&encoded);
     
    Json::Value r2; // 接收反序列化用
    std::cout<<encoded<<std::endl;
    Cloud::JsonUtil::UnSerialize(encoded,&r2);

    std::cout<<"Filename: "<<r2["Filename"]<<std::endl;
    std::cout<<"FSize: "<<r2["FSize"]<<std::endl;
    std::cout<<"LastATime: "<<r2["LastATime"]<<std::endl;
    std::cout<<"LastMTime: "<<r2["LastMTime"]<<std::endl;

}

void JsonUtilTest(){
    const char *name = "张三";
    int age = 22;
    float score[] = {100,99.5,50};

    Json::Value root;
    root["姓名"] = name;
    root["年龄"] = age;
    root["成绩"].append(score[0]);
    root["成绩"].append(score[1]);
    root["成绩"].append(score[2]);

    std::string encoded;
    Cloud::JsonUtil::Serialize(root,&encoded);

    std::cout<<encoded<<std::endl;
    Json::Value decoded;

    Cloud::JsonUtil::UnSerialize(encoded,&decoded);
    
    std::cout<<"姓名: "<<decoded["姓名"].asString()<<std::endl;
    std::cout<<"年龄: "<<decoded["年龄"].asInt()<<std::endl;
    std::cout<<"成绩: "<<decoded["成绩"][0].asFloat()<<", "<<decoded["成绩"][1].asFloat()<<", "<<decoded["成绩"][2].asFloat()<<"  "<<std::endl;
    // 可不指明 类型

}


void ConfigTest(){
    Cloud::Config *config = Cloud::Config::GetInstance();
    std::cout<<config->GetHotTime()<<std::endl;
    std::cout<<config->GetServerPort()<<std::endl;
    std::cout<<config->GetServerIP()<<std::endl;
    std::cout<<config->GetDownloadPrefix()<<std::endl;
    std::cout<<config->GetPackFileSuffix()<<std::endl;
    std::cout<<config->GetPackDir()<<std::endl;
    std::cout<<config->GetBackDir()<<std::endl;
    std::cout<<config->GetBackupFile()<<std::endl;
}


void DataTest(const std::string filename){

    Cloud::DataManager data; // 实例化一个数据类
    std::vector<Cloud::BackupInfo> vv;
    data.GetAll(&vv);
    
    for(auto &it : vv){
        std::cout<<it.pack_flag<<std::endl;
        std::cout<<it.fsize<<std::endl;
        std::cout<<it.mtime<<std::endl;
        std::cout<<it.atime<<std::endl;
        std::cout<<it.real_path<<std::endl;
        std::cout<<it.pack_path<<std::endl;
        std::cout<<it.url<<std::endl;
    }

   
/*
    std::cout<<"------------Insert and GetOneByURL-----------\n";
    Cloud::BackupInfo info; // 创建一个信息类
    if(!info.NewBackupInfo(filename)) return; // 实例化 获取对应信息

    Cloud::DataManager data; // 实例化一个数据类
    data.Insert(info); // 将信息结构体插入到数据类中的哈希表中

    Cloud::BackupInfo tmp; // 创建一个临时的信息类
    data.GetOneByURL("/download/bundle.h",&tmp); // 从数据类中的结构体中找到对应信息类
    
    std::cout<<tmp.pack_flag<<std::endl;
    std::cout<<tmp.fsize<<std::endl;
    std::cout<<tmp.mtime<<std::endl;
    std::cout<<tmp.atime<<std::endl;
    std::cout<<tmp.real_path<<std::endl;
    std::cout<<tmp.pack_path<<std::endl;
    std::cout<<tmp.url<<std::endl;

    std::cout<<"------------Update and GetOneByRealPath-------------\n";
    tmp.pack_flag = 1;
    data.Update(tmp);

    Cloud::BackupInfo tmp2;
    std::string realpath = tmp.real_path;
    data.GetOneByRealPath(realpath,&tmp2);

    std::cout<<tmp2.pack_flag<<std::endl;
    std::cout<<tmp2.fsize<<std::endl;
    std::cout<<tmp2.mtime<<std::endl;
    std::cout<<tmp2.atime<<std::endl;
    std::cout<<tmp2.real_path<<std::endl;
    std::cout<<tmp2.pack_path<<std::endl;
    std::cout<<tmp2.url<<std::endl;

    std::cout<<"----------------------GetAll-------------------\n";
    std::vector<Cloud::BackupInfo> vv;
    data.GetAll(&vv);
    
    for(auto &it : vv){
        std::cout<<it.pack_flag<<std::endl;
        std::cout<<it.fsize<<std::endl;
        std::cout<<it.mtime<<std::endl;
        std::cout<<it.atime<<std::endl;
        std::cout<<it.real_path<<std::endl;
        std::cout<<it.pack_path<<std::endl;
        std::cout<<it.url<<std::endl;
    }

*/
}





Cloud::DataManager *_data; 
void HotTest(){
    _data = new Cloud::DataManager();
    Cloud::HotManager hot;
    hot.RunModule();

}


void ServiceTest(){
    Cloud::Service srv;
    srv.RunModule();

}


int main(int argc, char *argv[])
{
    _data = new Cloud::DataManager();
    /*  ---------------   Test1   -------------------  */ 
    //    FileUtilTest(argv[1]);

    /*  ---------------   Test2   -------------------  */ 
    // JsonUtilTest();

    /*  ---------------   Test3   -------------------  */ 
    // ConfigTest();
    
    /*  ---------------   Test4   -------------------  */ 
    // DataTest(argv[1]);

    /*  ---------------   Test5   -------------------  */ 
    // HotTest()
    
    /*  ---------------   Test6   -------------------  */ 
    // ServiceTest();

    /*  ---------------   Test7   -------------------  */ 
    std::thread thread_service(ServiceTest);
    std::thread thread_hot_manager(HotTest);

    thread_hot_manager.join();
    thread_service.join();

    return 0;
}

